<?php

namespace Home\Service;

use Home\Common\FIdConst;

/**
 * 售后单Service
 *
 * @author 李静波
 */
class ASBillService extends PSIBaseService {

	/**
	 * 生成新的销售订单号
	 */
	private function genNewBillRef() {
		// $bs = new BizConfigService();
		// $pre = $bs->getSOBillRefPre();
		$pre = "AS";
		
		$mid = date("Ymd");
		
		$sql = "select ref from t_as_bill where ref like '%s' order by ref desc limit 1";
		$data = M()->query($sql, $pre . $mid . "%");
		$sufLength = 3;
		$suf = str_pad("1", $sufLength, "0", STR_PAD_LEFT);
		if ($data) {
			$ref = $data[0]["ref"];
			$nextNumber = intval(substr($ref, strlen($pre . $mid))) + 1;
			$suf = str_pad($nextNumber, $sufLength, "0", STR_PAD_LEFT);
		}
		
		return $pre . $mid . $suf;
	}

	private function modeTypeToLabel($modeType) {
		switch ($modeType) {
			case 1 :
				return "现金收入";
			case 2 :
				return "转账收入";
			case 3 :
				return "POS刷卡";
			case 4 :
				return "赊销";
			default :
				return "";
		}
	}

	private function billStatusToLabel($billStatus) {
		switch ($billStatus) {
			case 0 :
				return "待处理";
			case 1000 :
				return "已审核";
			case 2000 :
				return "处理完毕";
			case 3000 :
				return "中途关闭";
			default :
				return "";
		}
	}

	private function bizTypeToLabel($bizType) {
		switch ($bizType) {
			case 0 :
				return "退货";
			case 1 :
				return "换货";
			case 2 :
				return "补发";
			default :
				return "";
		}
	}

	private function salesModeExists($salesModeId, $db) {
		if (! $db) {
			$db = M();
		}
		
		$sql = "select count(*) as cnt from t_sales_mode where id = '%s' ";
		$data = $db->query($sql, $salesModeId);
		return $data[0]["cnt"] == 1;
	}

	public function asbillList($params) {
		if ($this->isNotOnline()) {
			return $this->emptyResult();
		}
		
		$page = $params["page"];
		$start = $params["start"];
		$limit = $params["limit"];
		
		$billStatus = $params["billStatus"];
		$ref = $params["ref"];
		$fromDT = $params["fromDT"];
		$toDT = $params["toDT"];
		$warehouseId = $params["warehouseId"];
		$customerId = $params["customerId"];
		$bizType = $params["bizType"];
		
		$db = M();
		$sql = "select w.id, w.ref, w.bizdt, c.name as customer_name, u.name as biz_user_name,
				 	user.name as input_user_name,
				 	w.bill_status, w.date_created, w.biz_type, w.srv_summary,
					w.in_warehouse_id, w.out_warehouse_id, confirm_user_id, confirm_dt
				 from t_as_bill w, t_customer c, t_user u, t_user user
				 where (w.customer_id = c.id) and (w.biz_user_id = u.id)
				 and (w.input_user_id = user.id)";
		$queryParams = array();
		
		$ds = new DataOrgService();
		$rs = $ds->buildSQL(FIdConst::AFTER_SALES, "w");
		if ($rs) {
			$sql .= " and " . $rs[0];
			$queryParams = $rs[1];
		}
		
		if ($billStatus != - 1) {
			$sql .= " and (w.bill_status = %d) ";
			$queryParams[] = $billStatus;
		}
		if ($ref) {
			$sql .= " and (w.ref like '%s') ";
			$queryParams[] = "%{$ref}%";
		}
		if ($fromDT) {
			$sql .= " and (w.bizdt >= '%s') ";
			$queryParams[] = $fromDT;
		}
		if ($toDT) {
			$sql .= " and (w.bizdt <= '%s') ";
			$queryParams[] = $toDT;
		}
		if ($customerId) {
			$sql .= " and (w.customer_id = '%s') ";
			$queryParams[] = $customerId;
		}
		if ($warehouseId) {
			$sql .= " and (w.in_warehouse_id = '%s' or w.out_warehouse_id = '%s') ";
			$queryParams[] = $warehouseId;
			$queryParams[] = $warehouseId;
		}
		if ($bizType != - 1) {
			$sql .= " and (w.biz_type = %d) ";
			$queryParams[] = $bizType;
		}
		
		$sql .= " order by w.bizdt desc, w.ref desc
				 limit %d, %d";
		$queryParams[] = $start;
		$queryParams[] = $limit;
		$data = $db->query($sql, $queryParams);
		$result = array();
		
		foreach ( $data as $v ) {
			$item = array(
					"id" => $v["id"],
					"ref" => $v["ref"],
					"bizDate" => $this->toYMD($v["bizdt"]),
					"customerName" => $v["customer_name"],
					"inputUserName" => $v["input_user_name"],
					"bizUserName" => $v["biz_user_name"],
					"dateCreated" => $v["date_created"],
					"billStatus" => $this->billStatusToLabel($v["bill_status"]),
					"bizType" => $this->bizTypeToLabel($v["biz_type"]),
					"srvSummary" => $v["srv_summary"],
					"confirmDT" => $v["confirm_dt"]
			);
			
			$bizType = $v["biz_type"];
			
			if ($bizType == 0 || $bizType == 1) {
				$inWarehouseId = $v["in_warehouse_id"];
				if ($inWarehouseId) {
					$sql = "select name from t_warehouse where id = '%s' ";
					$d = $db->query($sql, $inWarehouseId);
					if ($d) {
						$item["inWarehouseName"] = $d[0]["name"];
					}
				}
			}
			
			if ($bizType == 1 || $bizType == 2) {
				$outWarehouseId = $v["out_warehouse_id"];
				if ($outWarehouseId) {
					$sql = "select name from t_warehouse where id = '%s' ";
					$d = $db->query($sql, $outWarehouseId);
					if ($d) {
						$item["outWarehouseName"] = $d[0]["name"];
					}
				}
			}
			
			$confirmUserId = $v["confirm_user_id"];
			if ($confirmUserId) {
				$sql = "select name from t_user where id = '%s' ";
				$d = $db->query($sql, $confirmUserId);
				if ($d) {
					$item["confirmUserName"] = $d[0]["name"];
				}
			}
			
			$result[] = $item;
		}
		
		$sql = "select count(*) as cnt
				 from t_as_bill w, t_customer c, t_user u, t_user user
				 where (w.customer_id = c.id) and (w.biz_user_id = u.id)
				 and (w.input_user_id = user.id) ";
		$queryParams = array();
		
		$ds = new DataOrgService();
		$rs = $ds->buildSQL(FIdConst::AFTER_SALES, "w");
		if ($rs) {
			$sql .= " and " . $rs[0];
			$queryParams = $rs[1];
		}
		
		if ($billStatus != - 1) {
			$sql .= " and (w.bill_status = %d) ";
			$queryParams[] = $billStatus;
		}
		if ($ref) {
			$sql .= " and (w.ref like '%s') ";
			$queryParams[] = "%{$ref}%";
		}
		if ($fromDT) {
			$sql .= " and (w.bizdt >= '%s') ";
			$queryParams[] = $fromDT;
		}
		if ($toDT) {
			$sql .= " and (w.bizdt <= '%s') ";
			$queryParams[] = $toDT;
		}
		if ($customerId) {
			$sql .= " and (w.customer_id = '%s') ";
			$queryParams[] = $customerId;
		}
		if ($warehouseId) {
			$sql .= " and (w.in_warehouse_id = '%s' or w.out_warehouse_id = '%s') ";
			$queryParams[] = $warehouseId;
			$queryParams[] = $warehouseId;
		}
		if ($bizType != - 1) {
			$sql .= " and (w.biz_type = %d) ";
			$queryParams[] = $bizType;
		}
		
		$data = $db->query($sql, $queryParams);
		$cnt = $data[0]["cnt"];
		
		return array(
				"dataList" => $result,
				"totalCount" => $cnt
		);
	}

	public function asBillInfo($params) {
		if ($this->isNotOnline()) {
			return $this->emptyResult();
		}
		
		$id = $params["id"];
		
		$db = M();
		
		if ($id) {
			// 编辑售后单
			$sql = "select a.id, a.ref, a.bizdt, a.customer_id, a.in_warehouse_id,
						a.out_warehouse_id, a.biz_user_id, a.biz_type, a.bill_status,
						a.srv_summary, a.sobill_id, a.sobill_ref, a.payment_type, a.receiving_type,
						a.sales_mode_id, c.name as customer_name, u.name as biz_user_name
					from t_as_bill a, t_customer c, t_user u
					where a.id = '%s' and a.customer_id = c.id
						and a.biz_user_id = u.id ";
			$data = $db->query($sql, $id);
			if (! $data) {
				return $this->emptyResult();
			}
			
			$v = $data[0];
			$result = array(
					"id" => $v["id"],
					"ref" => $v["ref"],
					"bizDT" => $this->toYMD($v["bizdt"]),
					"customerId" => $v["customer_id"],
					"customerName" => $v["customer_name"],
					"inWarehouseId" => $v["in_warehouse_id"],
					"outWarehouseId" => $v["out_warehouse_id"],
					"bizUserId" => $v["biz_user_id"],
					"bizUserName" => $v["biz_user_name"],
					"bizType" => $v["biz_type"],
					"billStatus" => $v["bill_status"],
					"srvSummary" => $v["srv_summary"],
					"soBillRef" => $v["sobill_ref"],
					"soBillId" => $v["sobill_id"],
					"paymentType" => $v["payment_type"],
					"receivingType" => $v["receiving_type"],
					"salesModeId" => $v["sales_mode_id"]
			);
			
			$inWarehouseId = $v["in_warehouse_id"];
			$outWarehouseId = $v["out_warehouse_id"];
			
			if ($inWarehouseId) {
				$sql = "select name from t_warehouse where id = '%s' ";
				$data = $db->query($sql, $inWarehouseId);
				if ($data) {
					$result["inWarehouseName"] = $data[0]["name"];
				}
			}
			
			if ($outWarehouseId) {
				$sql = "select name from t_warehouse where id = '%s' ";
				$data = $db->query($sql, $outWarehouseId);
				if ($data) {
					$result["outWarehouseName"] = $data[0]["name"];
				}
			}
			
			$sql = "select s.wsbilldetail_id, s.goods_id, g.code, g.name, g.spec, u.name as unit_name,
				   s.rejection_goods_count, s.rejection_goods_price, s.rejection_sale_money,
					s.qc_begin_dt, s.qc_end_dt, s.expiration, s.goods_count, s.goods_price,
					s.goods_money
				from t_as_bill_rej_detail s, t_goods g, t_goods_unit u
				where s.asbill_id = '%s' and s.goods_id = g.id and g.unit_id = u.id
				order by s.show_order";
			$data = $db->query($sql, $id);
			
			$rejItems = array();
			
			foreach ( $data as $v ) {
				$item = array(
						"id" => $v["wsbilldetail_id"],
						"goodsId" => $v["goods_id"],
						"goodsCode" => $v["code"],
						"goodsName" => $v["name"],
						"goodsSpec" => $v["spec"],
						"unitName" => $v["unit_name"],
						"rejCount" => $v["rejection_goods_count"],
						"rejPrice" => $v["rejection_goods_price"],
						"rejMoney" => $v["rejection_sale_money"],
						"goodsCount" => $v["goods_count"],
						"goodsPrice" => $v["goods_price"],
						"goodsMoney" => $v["goods_money"]
				);
				$qcBeginDT = $this->toYmdForQC($v["qc_begin_dt"]);
				if ($qcBeginDT) {
					$item["qcBeginDT"] = $qcBeginDT;
				}
				$expiration = $v["expiration"];
				if ($expiration) {
					$item["expiration"] = $expiration;
				}
				$qcEndDT = $this->toYmdForQC($v["qc_end_dt"]);
				if ($qcEndDT) {
					$item["qcEndDT"] = $qcEndDT;
				}
				
				$rejItems[] = $item;
			}
			
			$result["rejItems"] = $rejItems;
			
			$sql = "select s.id, g.id as goods_id, g.code, g.name, g.spec, u.name as unit_name,
				   s.goods_count, s.goods_price, s.goods_money,
					s.qc_begin_dt, s.qc_end_dt, s.expiration
				from t_as_bill_ex_detail s, t_goods g, t_goods_unit u
				where s.asbill_id = '%s' and s.goods_id = g.id and g.unit_id = u.id
				order by s.show_order";
			$data = $db->query($sql, $id);
			
			$exItems = array();
			
			foreach ( $data as $v ) {
				$item = array(
						"id" => $v["id"],
						"goodsId" => $v["goods_id"],
						"goodsCode" => $v["code"],
						"goodsName" => $v["name"],
						"goodsSpec" => $v["spec"],
						"unitName" => $v["unit_name"],
						"goodsCount" => $v["goods_count"],
						"goodsPrice" => $v["goods_price"],
						"goodsMoney" => $v["goods_money"]
				);
				$qcBeginDT = $this->toYmdForQC($v["qc_begin_dt"]);
				if ($qcBeginDT) {
					$item["qcBeginDT"] = $qcBeginDT;
				}
				$expiration = $v["expiration"];
				if ($expiration) {
					$item["expiration"] = $expiration;
				}
				$qcEndDT = $this->toYMD($v["qc_end_dt"]);
				if ($qcEndDT) {
					$item["qcEndDT"] = $qcEndDT;
				}
				
				$exItems[] = $item;
			}
			
			$result["exItems"] = $exItems;
		} else {
			// 新建售后单
			$result = array();
			
			$us = new UserService();
			$result["bizUserId"] = $us->getLoginUserId();
			$result["bizUserName"] = $us->getLoginUserName();
		}
		
		// 销售收入方式
		$sql = "select id, mode_type, name
				from t_sales_mode
				order by mode_type";
		$data = $db->query($sql);
		$sm = array();
		foreach ( $data as $i => $v ) {
			$sm[$i]["id"] = $v["id"];
			$sm[$i]["text"] = $this->modeTypeToLabel($v["mode_type"]) . " - " . $v["name"];
		}
		$result["salesModeList"] = $sm;
		
		return $result;
	}

	public function selectSOBillList($params) {
		if ($this->isNotOnline()) {
			return $this->emptyResult();
		}
		
		$page = $params["page"];
		$start = $params["start"];
		$limit = $params["limit"];
		
		$ref = $params["ref"];
		$customerId = $params["customerId"];
		$warehouseId = $params["warehouseId"];
		$fromDT = $params["fromDT"];
		$toDT = $params["toDT"];
		
		$db = M();
		$sql = "select w.id, w.ref, w.biz_dt, c.name as customer_name, u.name as biz_user_name,
				 user.name as input_user_name, h.name as warehouse_name, w.goods_money
				 from t_so_bill w, t_customer c, t_user u, t_user user, t_warehouse h
				 where (w.customer_id = c.id) and (w.biz_user_id = u.id)
				 and (w.input_user_id = user.id) and (w.warehouse_id = h.id)
				 and (w.bill_status = 1000) ";
		$queryParamas = array();
		
		$ds = new DataOrgService();
		$rs = $ds->buildSQL(FIdConst::AFTER_SALES, "w");
		if ($rs) {
			$sql .= " and " . $rs[0];
			$queryParamas = $rs[1];
		}
		
		if ($ref) {
			$sql .= " and (w.ref like '%s') ";
			$queryParamas[] = "%$ref%";
		}
		if ($customerId) {
			$sql .= " and (w.customer_id = '%s') ";
			$queryParamas[] = $customerId;
		}
		if ($warehouseId) {
			$sql .= " and (w.warehouse_id = '%s') ";
			$queryParamas[] = $warehouseId;
		}
		if ($fromDT) {
			$sql .= " and (w.biz_dt >= '%s') ";
			$queryParamas[] = $fromDT;
		}
		if ($toDT) {
			$sql .= " and (w.biz_dt <= '%s') ";
			$queryParamas[] = $toDT;
		}
		$sql .= " order by w.ref desc
				 limit %d, %d";
		$queryParamas[] = $start;
		$queryParamas[] = $limit;
		$data = $db->query($sql, $queryParamas);
		$result = array();
		
		foreach ( $data as $v ) {
			$item = array(
					"id" => $v["id"],
					"ref" => $v["ref"],
					"bizDate" => $this->toYMD($v["biz_dt"]),
					"customerName" => $v["customer_name"],
					"inputUserName" => $v["input_user_name"],
					"bizUserName" => $v["biz_user_name"],
					"warehouseName" => $v["warehouse_name"],
					"amount" => $v["goods_money"]
			);
			
			$result[] = $item;
		}
		
		$sql = "select count(*) as cnt
				 from t_so_bill w, t_customer c, t_user u, t_user user, t_warehouse h
				 where (w.customer_id = c.id) and (w.biz_user_id = u.id)
				 and (w.input_user_id = user.id) and (w.warehouse_id = h.id)
				 and (w.bill_status >= 1000) ";
		$queryParamas = array();
		$ds = new DataOrgService();
		$rs = $ds->buildSQL(FIdConst::AFTER_SALES, "w");
		if ($rs) {
			$sql .= " and " . $rs[0];
			$queryParamas = $rs[1];
		}
		
		if ($ref) {
			$sql .= " and (w.ref like '%s') ";
			$queryParamas[] = "%$ref%";
		}
		if ($customerId) {
			$sql .= " and (w.customer_id = '%s') ";
			$queryParamas[] = $customerId;
		}
		if ($warehouseId) {
			$sql .= " and (w.warehouse_id = '%s') ";
			$queryParamas[] = $warehouseId;
		}
		if ($fromDT) {
			$sql .= " and (w.biz_dt >= '%s') ";
			$queryParamas[] = $fromDT;
		}
		if ($toDT) {
			$sql .= " and (w.biz_dt <= '%s') ";
			$queryParamas[] = $toDT;
		}
		
		$data = $db->query($sql, $queryParamas);
		$cnt = $data[0]["cnt"];
		
		return array(
				"dataList" => $result,
				"totalCount" => $cnt
		);
	}

	public function getSOBillInfoForASBill($params) {
		if ($this->isNotOnline()) {
			return $this->emptyResult();
		}
		
		$result = array();
		
		$id = $params["id"];
		$db = M();
		$sql = "select c.name as customer_name, w.ref, h.id as warehouse_id,
				  h.name as warehouse_name, c.id as customer_id
				from t_so_bill w, t_customer c, t_warehouse h
				where w.id = '%s' and w.customer_id = c.id and w.warehouse_id = h.id ";
		$data = $db->query($sql, $id);
		if (! $data) {
			return $result;
		}
		
		$result["ref"] = $data[0]["ref"];
		$result["customerName"] = $data[0]["customer_name"];
		$result["warehouseId"] = $data[0]["warehouse_id"];
		$result["warehouseName"] = $data[0]["warehouse_name"];
		$result["customerId"] = $data[0]["customer_id"];
		
		$sql = "select d.id, g.id as goods_id, g.code, g.name, g.spec, u.name as unit_name, d.goods_count,
					d.goods_price, d.goods_money, d.qc_begin_dt, d.qc_end_dt, d.expiration
				from t_so_bill_detail d, t_goods g, t_goods_unit u
				where d.sobill_id = '%s' and d.goods_id = g.id and g.unit_id = u.id
				order by d.show_order";
		$data = $db->query($sql, $id);
		$items = array();
		
		foreach ( $data as $v ) {
			$item = array(
					"id" => $v["id"],
					"goodsId" => $v["goods_id"],
					"goodsCode" => $v["code"],
					"goodsName" => $v["name"],
					"goodsSpec" => $v["spec"],
					"unitName" => $v["unit_name"],
					"goodsCount" => $v["goods_count"],
					"goodsPrice" => $v["goods_price"],
					"goodsMoney" => $v["goods_money"],
					"rejPrice" => $v["goods_price"]
			);
			
			$qcBeginDT = $this->toYmdForQC($v["qc_begin_dt"]);
			if ($qcBeginDT) {
				$item["qcBeginDT"] = $qcBeginDT;
			}
			$expiration = $v["expiration"];
			if ($expiration > 0) {
				$item["expiration"] = $expiration;
			}
			$qcEndDT = $this->toYmdForQC($v["qc_end_dt"]);
			if ($qcEndDT) {
				$item["qcEndDT"] = $qcEndDT;
			}
			
			$items[] = $item;
		}
		
		$result["items"] = $items;
		
		return $result;
	}

	public function editASBill($params) {
		if ($this->isNotOnline()) {
			return $this->notOnlineError();
		}
		
		$json = $params["jsonStr"];
		
		$bill = json_decode(html_entity_decode($json), true);
		if ($bill == null) {
			return $this->bad("传入的参数错误，不是正确的JSON格式");
		}
		
		$db = M();
		$db->startTrans();
		
		$id = $bill["id"];
		$bizType = $bill["bizType"];
		$bizDT = $bill["bizDT"];
		$customerId = $bill["customerId"];
		$inWarehouseId = $bill["inWarehouseId"];
		$outWarehouseId = $bill["outWarehouseId"];
		$srvSummary = $bill["srvSummary"];
		$bizUserId = $bill["bizUserId"];
		$paymentType = $bill["paymentType"];
		$revType = $bill["revType"];
		$salesModeId = $bill["salesModeId"];
		$soBillId = $bill["soBillId"];
		
		$rejItems = $bill["rejItems"];
		$exItems = $bill["exItems"];
		
		// 根据售后类型判断数据是否正确
		$ws = new WarehouseService();
		if ($bizType == 0) {
			// 退货
			if (! $ws->warehouseExists($inWarehouseId, $db)) {
				$db->rollback();
				return $this->bad("没有选择退货入库仓库");
			}
			
			$paymentTypeIsOK = $paymentType == 0 || $paymentType == 1 || $paymentType == 2;
			if (! $paymentTypeIsOK) {
				$db->rollback();
				return $this->bad("没有选择退货记账方式");
			}
		} else if ($bizType == 1) {
			// 换货
			if (! $ws->warehouseExists($inWarehouseId, $db)) {
				$db->rollback();
				return $this->bad("没有选择退货入库仓库");
			}
			$paymentTypeIsOK = $paymentType == 0 || $paymentType == 1 || $paymentType == 2;
			if (! $paymentTypeIsOK) {
				$db->rollback();
				return $this->bad("没有选择退货记账方式");
			}
			if (! $ws->warehouseExists($outWarehouseId, $db)) {
				$db->rollback();
				return $this->bad("没有选择发货出库仓库");
			}
			if (! $this->salesModeExists($salesModeId, $db)) {
				$db->rollback();
				return $this->bad("没有选择发货销售收入方式");
			}
			$revTypeIsOK = $revType == 0 || $revType == 1;
			if (! $revTypeIsOK) {
				$db->rollback();
				return $this->bad("没有选择发货记账方式");
			}
		} else if ($bizType == 2) {
			// 补发
			if (! $ws->warehouseExists($outWarehouseId, $db)) {
				$db->rollback();
				return $this->bad("没有选择发货出库仓库");
			}
			if (! $this->salesModeExists($salesModeId, $db)) {
				$db->rollback();
				return $this->bad("没有选择发货销售收入方式");
			}
			$revTypeIsOK = $revType == 0 || $revType == 1;
			if (! $revTypeIsOK) {
				$db->rollback();
				return $this->bad("没有选择发货记账方式");
			}
		} else {
			$db->rollback();
			return $this->bad("没有正确选择售后类型");
		}
		
		// 检查客户id
		$cs = new CustomerService();
		if (! $cs->customerExists($customerId, $db)) {
			$db->rollback();
			return $this->bad("没有选择客户");
		}
		
		// 检查销售订单是否存在
		$sql = "select ref from t_so_bill where id = '%s' ";
		$data = $db->query($sql, $soBillId);
		if (! $data) {
			$db->rollback();
			return $this->bad("选择的销售订单不存在");
		}
		$soBillRef = $data[0]["ref"];
		
		// 检查业务日期
		if (! $this->dateIsValid($bizDT)) {
			$db->rollback();
			return $this->bad("业务日期不正确");
		}
		
		// 检查业务员
		$us = new UserService();
		if (! $us->userExists($bizUserId, $db)) {
			$db->rollback();
			return $this->bad("没有选择业务员");
		}
		$userId = $us->getLoginUserId();
		$dataOrg = $us->getLoginUserDataOrg();
		$companyId = $us->getCompanyId();
		
		$idGen = new IdGenService();
		
		$log = null;
		if ($id) {
			// 编辑售后单
			$sql = "select ref, bill_status from t_as_bill where id = '%s' ";
			$data = $db->query($sql, $id);
			if (! $data) {
				$db->rollback();
				return $this->bad("要编辑的售后单不存在");
			}
			$ref = $data[0]["ref"];
			$billStatus = $data[0]["bill_status"];
			if ($billStatus > 0) {
				$db->rollback();
				return $this->bad("当前售后单已经开始处理，不能再编辑");
			}
			
			// 主表
			$sql = "update t_as_bill
					set bizdt = '%s', in_warehouse_id = '%s', out_warehouse_id = '%s',
						srv_summary = '%s', biz_user_id = '%s', payment_type = %d,
						receiving_type = %d, sales_mode_id = '%s'
					where id = '%s' ";
			$rc = $db->execute($sql, $bizDT, $inWarehouseId, $outWarehouseId, $srvSummary, 
					$bizUserId, $paymentType, $revType, $salesModeId, $id);
			if ($rc === false) {
				$db->rollback();
				return $this->sqlError(__LINE__);
			}
			
			// 清空明细表数据，新增明细表的代码在后面统一处理
			$sql = "delete from t_as_bill_rej_detail where asbill_id = '%s' ";
			$rc = $db->execute($sql, $id);
			if ($rc === false) {
				$db->rollback();
				return $this->sqlError(__LINE__);
			}
			$sql = "delete from t_as_bill_ex_detail where asbill_id = '%s' ";
			$rc = $db->execute($sql, $id);
			if ($rc === false) {
				$db->rollback();
				return $this->sqlError(__LINE__);
			}
			
			$log = "编辑售后单，单号[$ref]";
		} else {
			// 新建售后单
			$id = $idGen->newId($db);
			$ref = $this->genNewBillRef();
			
			// 主表
			$sql = "insert into t_as_bill (id, ref, customer_id, in_warehouse_id, out_warehouse_id,
						biz_user_id, bizdt, input_user_id, date_created, bill_status, biz_type,
						srv_summary, confirm_user_id, sobill_id, sobill_ref, data_org, company_id,
						payment_type, receiving_type, sales_mode_id)
					values ('%s', '%s', '%s', '%s', '%s',
						'%s', '%s', '%s', now(), 0, %d,
						'%s', '', '%s', '%s', '%s', '%s',
						%d, %d, '%s')";
			$rc = $db->execute($sql, $id, $ref, $customerId, $inWarehouseId, $outWarehouseId, 
					$bizUserId, $bizDT, $userId, $bizType, $srvSummary, $soBillId, $soBillRef, 
					$dataOrg, $companyId, $paymentType, $revType, $salesModeId);
			if ($rc === false) {
				$db->rollback();
				return $this->sqlError(__LINE__);
			}
			
			$log = "新建售后单，单号: {$ref} ";
		}
		
		// 明细表
		
		if ($bizType == 0 || $bizType == 1) {
			// 退货入库/换货入库
			
			foreach ( $rejItems as $i => $v ) {
				$sobillDetailId = $v["id"];
				$goodsId = $v["goodsId"];
				$goodsCount = $v["goodsCount"];
				$goodsPrice = $v["goodsPrice"];
				$goodsMoney = $v["goodsMoney"];
				$rejCount = $v["rejCount"];
				$rejPrice = $v["rejPrice"];
				$rejMoney = $v["rejMoney"];
				
				$qcBeginDT = $v["qcBeginDT"];
				if (! $qcBeginDT) {
					$qcBeginDT = "1970-01-01";
				}
				$expiration = $v["expiration"];
				if (! $expiration) {
					$expiration = 0;
				}
				$qcEndDT = date("Y-m-d", strtotime($qcBeginDT . " +$expiration day"));
				
				// 通过销售订单查询到销售出库单，从而获得出库成本单价
				$sql = "select ws_id from t_so_ws where so_id = '%s' ";
				$data = $db->query($sql, $soBillId);
				if (! $data) {
					continue;
				}
				$wsBillId = $data[0]["ws_id"];
				
				$sql = "select inventory_price, id
							from t_ws_bill_detail
							where wsbill_id = '%s' and goods_id = '%s' 
								and qc_begin_dt = '%s' and expiration = %d ";
				$data = $db->query($sql, $wsBillId, $goodsId, $qcBeginDT, $expiration);
				if (! $data) {
					continue;
				}
				$invPrice = $data[0]["inventory_price"];
				$wsbillDetailId = $data[0]["id"];
				
				$sql = "insert into t_as_bill_rej_detail (id, asbill_id, show_order, goods_id,
							goods_count, goods_price, goods_money, date_created, inventory_price,
							inventory_money, wsbilldetail_id, rejection_goods_count, rejection_goods_price,
							rejection_sale_money, data_org, company_id,
							qc_begin_dt, expiration, qc_end_dt)
							values ('%s', '%s', %d, '%s',
								%d, %f, %f, now(), %f,
								%f, '%s', %d, %f,
								%f, '%s', '%s',
								'%s', %d, '%s')";
				$rc = $db->execute($sql, $idGen->newId($db), $id, $i, $goodsId, $goodsCount, 
						$goodsPrice, $goodsMoney, $invPrice, $invPrice * $rejCount, $wsbillDetailId, 
						$rejCount, $rejPrice, $rejMoney, $dataOrg, $companyId, $qcBeginDT, 
						$expiration, $qcEndDT);
				if ($rc === false) {
					$db->rollback();
					return $this->sqlError(__LINE__);
				}
			}
			
			$sql = "select sum(rejection_sale_money) as sum_rej_money
					from t_as_bill_rej_detail
					where asbill_id = '%s' ";
			$data = $db->query($sql, $id);
			$sumRejMoney = $data[0]["sum_rej_money"];
			$sql = "update t_as_bill
					set rej_money = %f
					where id = '%s' ";
			$rc = $db->execute($sql, $sumRejMoney, $id);
			if ($rc === false) {
				$db->rollback();
				return $this->sqlError(__LINE__);
			}
		}
		
		if ($bizType == 1 || $bizType == 2) {
			// 换货出库/补发出库
			$showOrder = 0;
			foreach ( $exItems as $v ) {
				$goodsId = $v["goodsId"];
				if (! $goodsId) {
					continue;
				}
				$goodsCount = $v["goodsCount"];
				$goodsPrice = $v["goodsPrice"];
				$goodsMoney = $v["goodsMoney"];
				$qcBeginDT = $v["qcBeginDT"];
				if (! $qcBeginDT) {
					$qcBeginDT = "1970-01-01";
				}
				$expiration = $v["expiration"];
				if (! $expiration) {
					$expiration = 0;
				}
				$qcEndDT = date("Y-m-d", strtotime($qcBeginDT . " +$expiration day"));
				
				$sql = "insert into t_as_bill_ex_detail (id, asbill_id, show_order, goods_id, 
								goods_count, goods_price, goods_money, 
								date_created, data_org, company_id,
								qc_begin_dt, expiration, qc_end_dt)
							values ('%s', '%s', %d, '%s', %d, %f, %f, now(), '%s', '%s',
								'%s', %d, '%s')";
				$rc = $db->execute($sql, $idGen->newId($db), $id, $showOrder, $goodsId, $goodsCount, 
						$goodsPrice, $goodsMoney, $dataOrg, $companyId, $qcBeginDT, $expiration, 
						$qcEndDT);
				if ($rc === false) {
					$db->rollback();
					return $this->sqlError(__LINE__);
				}
				
				$showOrder ++;
			}
		}
		
		$bs = new BizlogService();
		if ($log) {
			$bs->insertBizlog($log, "售后服务");
		}
		
		$db->commit();
		
		return $this->ok($id);
	}

	public function asBillRejDetailList($params) {
		if ($this->isNotOnline()) {
			return $this->emptyResult();
		}
		
		$id = $params["id"];
		
		$db = M();
		
		$sql = "select s.id, g.code, g.name, g.spec, u.name as unit_name,
				   s.rejection_goods_count, s.rejection_goods_price, s.rejection_sale_money,
					s.qc_begin_dt, s.qc_end_dt, s.expiration
				from t_as_bill_rej_detail s, t_goods g, t_goods_unit u
				where s.asbill_id = '%s' and s.goods_id = g.id and g.unit_id = u.id
					and s.rejection_goods_count > 0
				order by s.show_order";
		$data = $db->query($sql, $id);
		
		$result = array();
		
		foreach ( $data as $v ) {
			$item = array(
					"id" => $v["id"],
					"goodsCode" => $v["code"],
					"goodsName" => $v["name"],
					"goodsSpec" => $v["spec"],
					"unitName" => $v["unit_name"],
					"rejCount" => $v["rejection_goods_count"],
					"rejPrice" => $v["rejection_goods_price"],
					"rejSaleMoney" => $v["rejection_sale_money"]
			);
			$qcBeginDT = $this->toYmdForQC($v["qc_begin_dt"]);
			if ($qcBeginDT) {
				$item["qcBeginDT"] = $qcBeginDT;
			}
			$expiration = $v["expiration"];
			if ($expiration) {
				$item["expiration"] = $expiration;
			}
			$qcEndDT = $this->toYmdForQC($v["qc_end_dt"]);
			if ($qcEndDT) {
				$item["qcEndDT"] = $qcEndDT;
			}
			
			$result[] = $item;
		}
		
		return $result;
	}

	public function asBillExDetailList($params) {
		if ($this->isNotOnline()) {
			return $this->emptyResult();
		}
		
		$id = $params["id"];
		
		$db = M();
		
		$sql = "select s.id, g.code, g.name, g.spec, u.name as unit_name,
				   s.goods_count, s.goods_price, s.goods_money,
					s.qc_begin_dt, s.qc_end_dt, s.expiration
				from t_as_bill_ex_detail s, t_goods g, t_goods_unit u
				where s.asbill_id = '%s' and s.goods_id = g.id and g.unit_id = u.id
				order by s.show_order";
		$data = $db->query($sql, $id);
		
		$result = array();
		
		foreach ( $data as $v ) {
			$item = array(
					"id" => $v["id"],
					"goodsCode" => $v["code"],
					"goodsName" => $v["name"],
					"goodsSpec" => $v["spec"],
					"unitName" => $v["unit_name"],
					"goodsCount" => $v["goods_count"],
					"goodsPrice" => $v["goods_price"],
					"goodsMoney" => $v["goods_money"]
			);
			$qcBeginDT = $this->toYmdForQC($v["qc_begin_dt"]);
			if ($qcBeginDT) {
				$item["qcBeginDT"] = $qcBeginDT;
			}
			$expiration = $v["expiration"];
			if ($expiration) {
				$item["expiration"] = $expiration;
			}
			$qcEndDT = $this->toYmdForQC($v["qc_end_dt"]);
			if ($qcEndDT) {
				$item["qcEndDT"] = $qcEndDT;
			}
			
			$result[] = $item;
		}
		
		return $result;
	}

	/**
	 * 删除售后单
	 */
	public function deleteASBill($params) {
		if ($this->isNotOnline()) {
			return $this->notOnlineError();
		}
		
		$id = $params["id"];
		
		$db = M();
		$db->startTrans();
		
		$sql = "select ref, bill_status from t_as_bill where id = '%s' ";
		$data = $db->query($sql, $id);
		if (! $data) {
			$db->rollback();
			return $this->bad("要删除的售后单不存在");
		}
		$ref = $data[0]["ref"];
		$billStatus = $data[0]["bill_status"];
		if ($billStatus > 0) {
			$db->rollback();
			return $this->bad("只有待处理的售后单才能删除");
		}
		
		$sql = "delete from t_as_bill_rej_detail where asbill_id = '%s' ";
		$rc = $db->execute($sql, $id);
		if ($rc === false) {
			$db->rollback();
			return $this->sqlError(__LINE__);
		}
		
		$sql = "delete from t_as_bill_ex_detail where asbill_id = '%s' ";
		$rc = $db->execute($sql, $id);
		if ($rc === false) {
			$db->rollback();
			return $this->sqlError(__LINE__);
		}
		
		$sql = "delete from t_as_bill where id = '%s' ";
		$rc = $db->execute($sql, $id);
		if ($rc === false) {
			$db->rollback();
			return $this->sqlError(__LINE__);
		}
		
		$log = "删除售后单，单号[$ref]";
		$bs = new BizlogService();
		$bs->insertBizlog($log, "售后服务");
		
		$db->commit();
		
		return $this->ok($id);
	}

	/**
	 * 审核售后单
	 */
	public function commitASBill($params) {
		if ($this->isNotOnline()) {
			return $this->notOnlineError();
		}
		
		$id = $params["id"];
		
		$db = M();
		$db->startTrans();
		
		$sql = "select ref, bill_status, biz_type 
				from t_as_bill 
				where id = '%s' ";
		$data = $db->query($sql, $id);
		if (! $data) {
			$db->rollback();
			return $this->bad("要审核的售后单不存在");
		}
		$ref = $data[0]["ref"];
		$billStatus = $data[0]["bill_status"];
		$bizType = $data[0]["biz_type"];
		
		if ($billStatus > 0) {
			$db->rollback();
			return $this->bad("当前售后单已经审核过，不能再次审核");
		}
		
		if ($bizType == 0) {
			// 退货
			
			// 生成退货入库单
			$srBillService = new SRBillService();
			$result = $srBillService->createSRBillFromASBill($id, $db);
			if (! $result["success"]) {
				$db->rollback();
				return $result;
			}
		} else if ($bizType == 1) {
			// 换货
			
			// 生成退货入库单
			$srBillService = new SRBillService();
			$result = $srBillService->createSRBillFromASBill($id, $db);
			if (! $result["success"]) {
				$db->rollback();
				return $result;
			}
			
			// 生成销售订单
			$soBillService = new SOBillService();
			$result = $soBillService->createSOBillFromASBill($id, $db);
			if (! $result["success"]) {
				$db->rollback();
				return $result;
			}
		} else if ($bizType == 2) {
			// 补发
			
			// 生成销售订单
			$soBillService = new SOBillService();
			$result = $soBillService->createSOBillFromASBill($id, $db);
			if (! $result["success"]) {
				$db->rollback();
				return $result;
			}
		} else {
			$db->rollback();
			return $this->bad("售后类型不正确，无法审核");
		}
		
		$us = new UserService();
		$userId = $us->getLoginUserId();
		
		$sql = "update t_as_bill
				set bill_status = 1000,
					confirm_user_id = '%s', 
					confirm_dt = now()
				where id = '%s' ";
		$rc = $db->execute($sql, $userId, $id);
		if ($rc === false) {
			$db->rollback();
			return $this->sqlError(__LINE__);
		}
		
		$log = "审核售后单[单号 = {$ref}]";
		$bs = new BizlogService();
		$bs->insertBizlog($log, "售后服务");
		$db->commit();
		
		return $this->ok($id);
	}

	/**
	 * 取消审核售后单
	 */
	public function cancelCommitASBill($params) {
		if ($this->isNotOnline()) {
			return $this->notOnlineError();
		}
		
		$id = $params["id"];
		
		$db = M();
		
		$db->startTrans();
		
		$sql = "select ref, bill_status,
					gen_srbill_id, gen_srbill_ref,
					gen_sobill_id, gen_sobill_ref
				from t_as_bill 
				where id = '%s' ";
		$data = $db->query($sql, $id);
		if (! $data) {
			$db->rollback();
			return $this->bad("要取消审核的售后单不存在");
		}
		
		$srBillId = $data[0]["gen_srbill_id"];
		$srBillRef = $data[0]["gen_srbill_ref"];
		
		$soBillId = $data[0]["gen_sobill_id"];
		$soBillRef = $data[0]["gen_sobill_ref"];
		
		$ref = $data[0]["ref"];
		
		$billStatus = $data[0]["bill_status"];
		if ($billStatus != 1000) {
			$db->rollback();
			return $this->bad("当前售后单没有审核，不用取消");
		}
		
		// 检查 生成的退货入库单状态
		if ($srBillId) {
			$sql = "select bill_status from t_sr_bill where id = '%s' ";
			$data = $db->query($sql, $srBillId);
			if ($data) {
				$billStatus = $data[0]["bill_status"];
				if ($billStatus > 0) {
					$db->rollback();
					return $this->bad("生成的退货入库单[单号={$srBillRef}]已经提交，所以本售后单也不能取消审核");
				}
			}
		}
		
		// 检查生成的销售订单状态
		if ($soBillId) {
			$sql = "select bill_status from t_so_bill where id = '%s' ";
			$data = $db->query($sql, $soBillId);
			if ($data) {
				$billStatus = $data[0]["bill_status"];
				if ($billStatus > 0) {
					$db->rollback();
					return $this->bad("生成的销售订单[单号={$soBillRef}]已经审核，所以本售后单也不能取消审核");
				}
			}
		}
		
		// 删除生成的退货入库单
		if ($srBillId) {
			$sql = "delete from t_sr_bill_detail where srbill_id = '%s' ";
			$rc = $db->execute($sql, $srBillId);
			if ($rc === false) {
				$db->rollback();
				return $this->sqlError(__LINE__);
			}
			
			$sql = "delete from t_sr_bill where id = '%s' ";
			$rc = $db->execute($sql, $srBillId);
			if ($rc === false) {
				$db->rollback();
				return $this->sqlError(__LINE__);
			}
		}
		
		// 删除生成的销售订单
		if ($soBillId) {
			$sql = "delete from t_so_bill_detail where sobill_id = '%s' ";
			$rc = $db->execute($sql, $soBillId);
			if ($rc === false) {
				$db->rollback();
				return $this->sqlError(__LINE__);
			}
			
			$sql = "delete from t_so_bill where id = '%s' ";
			$rc = $db->execute($sql, $soBillId);
			if ($rc === false) {
				$db->rollback();
				return $this->sqlError(__LINE__);
			}
		}
		
		// 设置本售后单的状态为待处理
		$sql = "update t_as_bill
				set bill_status = 0, gen_srbill_id = null, gen_srbill_ref = null,
					gen_sobill_id = null, gen_sobill_ref = null,
					confirm_user_id = null, 
					confirm_dt = null
				where id = '%s' ";
		$rc = $db->execute($sql, $id);
		if ($rc === false) {
			$db->rollback();
			return $this->sqlError(__LINE__);
		}
		
		// 记录日志
		$log = "取消审核售后单[单号 = {$ref}]";
		$bs = new BizlogService();
		$bs->insertBizlog($log, "售后服务");
		
		$db->commit();
		
		return $this->ok($id);
	}
}